﻿namespace EFS.RC.CCC.Presences
{
	/// <summary>
	/// Presences
	/// </summary>
	internal abstract class Operator<OperatorDeployment> : EFS.Common.ISelfDescriptor where OperatorDeployment : EFS.RC.CCC.Deployment.Entities.Operator
	{
		// sync acces
		private object synkAccess = new object();

		/// Operator deployemnt 
		private OperatorDeployment operatorDeployment = default(OperatorDeployment);

		// AD user
		EFS.AD.User adUser = null;

		/// <summary>
		/// On-line status
		/// </summary>
		public System.Boolean IsOnline { get; private set; }
		
		/// <summary>
		/// Available for conversation
		/// </summary>
		public virtual System.Boolean IsAvailable { get; private set; }

		/// <summary>
		/// Prence status changed delegate
		/// </summary>
		/// <param name="?"></param>
		protected delegate void PresenceStatusChanged();

		/// Call to presence status changed events
		protected PresenceStatusChanged OnPresenceStatusChanged = null;

		/// <summary>
		/// Prence status changed delegate
		/// </summary>
		/// <param name="?"></param>
		protected delegate void PresenceAvailabilityChanged(System.Boolean oldAvailability, System.Boolean newAvailability);

		/// Call to presence avail changed events
		protected PresenceAvailabilityChanged OnPresenceAvailabilityChanged = null;

		/// <summary>
		/// Constructor
		/// </summary>
		/// <param name="operatorDeployment"></param>
		public Operator(OperatorDeployment operatorDeployment)
		{
			// check
			EFS.Common.Verify.Reference(operatorDeployment, "operatorDeployment");

			// set
			this.operatorDeployment = operatorDeployment;

			// load AD data
			adUser = EFS.AD.Query.GetUser(CCC.Config.Settings.DomainName, operatorDeployment.DomainLogon);
		}

		/// <summary>
		/// SIP: Get
		/// </summary>
		public EFS.AD.User User
		{
			get { return adUser; }
		}

		/// <summary>
		/// Describe this
		/// </summary>
		/// <returns></returns>
		public virtual System.String Describe()
		{
			return System.String.Format("EFS.RC.CCC.Presences.Operators.Operator: {0} Online: {1} Available: {2}", Sip, IsOnline, IsAvailable);
		}

		/// <summary>
		/// Update deploymentOperator
		/// </summary>
		/// <param name="notification"></param>
		public void Update(Microsoft.Rtc.Collaboration.Presence.RemotePresentityNotification notification)
		{
			// log
			EFS.EventLog.Log.LogInfo("Update", this);

			// check
			EFS.Common.Verify.Reference(notification, "notification");

			// availability
			System.Int64 availability = notification.AggregatedPresenceState.AvailabilityValue;

			// loack access
			lock (synkAccess)
			{
				// check online
				IsOnline = availability >= (System.Int64)Microsoft.Rtc.Collaboration.Presence.PresenceAvailability.Online; 
				
				// check busy
				System.Boolean isAvailable = IsOnline && availability < (System.Int64)Microsoft.Rtc.Collaboration.Presence.PresenceAvailability.Busy;
				if (IsAvailable != isAvailable)
				{
					// presence status changed, call event
					if (null != OnPresenceAvailabilityChanged)
					{
						OnPresenceAvailabilityChanged(IsAvailable, isAvailable);
					}	

					// set
					IsAvailable = isAvailable;
				}

				// log status
				EFS.EventLog.Log.LogInfo("Update : New status", this);		
			}

			// presence status changed, call event
			if (null != OnPresenceStatusChanged)
			{
				OnPresenceStatusChanged();
			}
		}
	}
}
